package com.hqd.ch03.v14.reader.xml.namespace.support;

import com.hqd.ch03.v14.config.BeanDefinition;
import com.hqd.ch03.v14.reader.xml.namespace.NamespaceHandler;
import com.hqd.ch03.v14.reader.xml.parse.BeanDefinitionDecorator;
import com.hqd.ch03.v14.reader.xml.parse.BeanDefinitionParser;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import java.util.HashMap;
import java.util.Map;

public abstract class NamespaceHandlerSupport implements NamespaceHandler {
    /**
     * BeanDefinition自定义标签解析器，eg:
     * <beans>
     * *     <a></a>
     * </beans>
     */
    private final Map<String, BeanDefinitionParser> parsers = new HashMap<>();
    /**
     * bean子标签解析器，eg:
     * <beans>
     * *     <bean>
     * *         <a></a>
     * *     </bean>
     * </beans>
     */
    private final Map<String, BeanDefinitionDecorator> decorators = new HashMap<>();
    /**
     * 自定义属性，eg:
     * <beans>
     * *     <bean name="xx" a="xx"></bean>
     * </beans>
     */
    private final Map<String, BeanDefinitionDecorator> attributeDecorators = new HashMap<>();

    @Override
    public BeanDefinition parse(Element element) {
        BeanDefinitionParser parser = findParserForElement(element);
        return (parser != null ? parser.parse(element) : null);
    }

    protected BeanDefinitionParser findParserForElement(Element element) {
        String localName = element.getLocalName();
        return this.parsers.get(localName);
    }

    @Override
    public BeanDefinition decorate(Node node, BeanDefinition definition) {
        BeanDefinitionDecorator decorator = findDecoratorForNode(node);
        return (decorator != null ? decorator.decorate(node, definition) : null);
    }

    private BeanDefinitionDecorator findDecoratorForNode(Node node) {
        String localName = node.getLocalName();
        if (node instanceof Element) {//自定义子节点
            return this.decorators.get(localName);
        } else if (node instanceof Attr) {//自定义标签属性
            return this.attributeDecorators.get(localName);
        } else {
            throw new RuntimeException(String.format("【%s】节点解析异常", node));
        }
    }

    protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
        this.parsers.put(elementName, parser);
    }

    protected final void registerBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator dec) {
        this.decorators.put(elementName, dec);
    }

    protected final void registerBeanDefinitionDecoratorForAttribute(String attrName, BeanDefinitionDecorator dec) {
        this.attributeDecorators.put(attrName, dec);
    }
}
